package com.code2roc.fastboot.system.org.bizlogic;


import com.code2roc.fastboot.system.org.model.SystemDeptDO;
import com.code2roc.fastboot.system.org.service.ISystemDeptService;
import com.code2roc.fastboot.system.setting.service.ISystemMenuSettingService;
import com.code2roc.fastboot.model.BaseBootLogic;
import com.code2roc.fastboot.util.BootUtil;
import com.code2roc.fastboot.framework.util.CommonUtil;
import com.code2roc.fastboot.framework.util.FileUtil;
import com.code2roc.fastboot.framework.util.LogUtil;
import com.code2roc.fastboot.framework.util.StringUtil;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class DeptLogic extends BaseBootLogic {
    @Autowired
    private ISystemDeptService service;
    @Autowired
    private ISystemMenuSettingService menuSettingService;

    public void insert(SystemDeptDO entity) {
        service.insert(entity);
    }

    public void delete(String row_id) {
        service.delete(row_id);
        menuSettingService.deleteSettingBySettingID(row_id);
    }

    public void update(SystemDeptDO entity) {
        service.update(entity);
        authUtil.refreshTokenInfo();
    }

    public SystemDeptDO detail(String row_id) {
        return service.selectOne(row_id);
    }

    public List<String> selectAllSubDepyByDGuid(String parent_id, List<SystemDeptDO> lst_All) {
        List<String> deptIDList = new ArrayList<String>();
        deptIDList.add(parent_id);
        selectSubList(lst_All, parent_id, deptIDList);
        return deptIDList;
    }

    private void selectSubList(List<SystemDeptDO> lst_All, String parent_id, List<String> deptIDList) {
        List<SystemDeptDO> list = lst_All.stream().filter((SystemDeptDO f) -> f.getParent_id().equals(parent_id)).collect(Collectors.toList());
        if (list.size() > 0) {
            for (SystemDeptDO dept : list) {
                deptIDList.add(dept.getRow_id());
                selectSubList(lst_All, dept.getRow_id(), deptIDList);
            }
        }

    }

    public String exportData(List<String> deptIDList){
        String fileid = "";
        try {
            DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
            Calendar calendar = Calendar.getInstance();
            String dateName = df.format(calendar.getTime());
            fileid = "DeptExport_" + dateName + CommonUtil.getNewGuid();
            String filename = fileid + ".xml";
            String filefullpath = "tempfiles/export/" + filename;
            FileUtil.initfloderPath("tempfiles/export/" );
            Document doc = DocumentHelper.createDocument();
            Element root = doc.addElement("orgfile");
            Element filetype = root.addElement("filetype");
            filetype.setText("dept");

            Element deptlist = root.addElement("deptlist");
            List<SystemDeptDO> deptDOAllList = service.selectAllList();
            List<String> subDGuidList = new ArrayList<>();
            for (String deptID:deptIDList) {
                subDGuidList.addAll(selectAllSubDepyByDGuid(deptID,deptDOAllList));
            }
            subDGuidList = subDGuidList.stream().distinct().collect(Collectors.toList());
            for (String dguid : subDGuidList) {
                SystemDeptDO deptDO = detail(dguid);
                Element dept = deptlist.addElement("dept");
                for (Field field : deptDO.getClass().getDeclaredFields()) {
                    if (!Modifier.isStatic(field.getModifiers())) {
                        field.setAccessible(true);
                        Element tablefield = dept.addElement(field.getName());
                        tablefield.setText(String.valueOf(field.get(deptDO)));
                    }
                }
            }

            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("utf-8");
            FileOutputStream out;
            out = new FileOutputStream(filefullpath);
            XMLWriter writer = new XMLWriter(out, format);
            writer.write(doc);
            writer.close();

            StringBuilder builder = new StringBuilder();
            builder.append("导出部门信息成功！" + CommonUtil.getNewLine());
            LogUtil.writeLog("org/dept", "log", builder.toString());
        } catch (Exception e) {
            e.printStackTrace();
            StringBuilder builder = new StringBuilder();
            builder.append("导出部门信息失败！" + CommonUtil.getNewLine());
            builder.append("失败异常信息:" + CommonUtil.getNewLine());
            builder.append(e.getMessage() + CommonUtil.getNewLine());
            builder.append("失败堆栈信息:" + CommonUtil.getNewLine());
            builder.append(e.getStackTrace());
            LogUtil.writeLog("org/dept", "log", builder.toString());
        }
        return fileid;
    }

    @Transactional(rollbackFor = {Exception.class}, isolation = Isolation.READ_UNCOMMITTED)
    public String importData(InputStream stream) {
        String errormsg = "";
        Exception exception = null;
        try {
            //解析xml
            SAXReader reader = new SAXReader();
            Document document = reader.read(stream);
            Element root = document.getRootElement();
            Element filetype = root.element("filetype");
            List<Element> deptlist = root.element("deptlist").elements("dept");
            if (filetype != null && filetype.getText().equals("dept")) {
                for (Element dept : deptlist) {
                    SystemDeptDO deptDO = new SystemDeptDO();
                    for (Field field : deptDO.getClass().getDeclaredFields()) {
                        if (!Modifier.isStatic(field.getModifiers())) {
                            field.setAccessible(true);
                            Element filednode = dept.element(field.getName());
                            field.set(deptDO,  BootUtil.convetXmlContent2FieldContent(filednode.getText(), field.getType()));
                        }
                    }
                    SystemDeptDO dbinfo = service.selectOne(deptDO.getRow_id());
                    if(dbinfo==null){
                        insert(deptDO);
                    }else{
                        update(deptDO);
                    }
                }
            } else {
                errormsg = "导入文件不是部门文件！";
            }
        } catch (Exception e) {
            exception = e;
            errormsg = "导入失败";
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();
        } finally {
            StringBuilder builder = new StringBuilder();
            if (StringUtil.isEmpty(errormsg)) {
                builder.append("导入部门成功！" + CommonUtil.getNewLine());
            } else {
                builder.append("导入部门失败！" + CommonUtil.getNewLine());
            }
            if (!StringUtil.isEmpty(errormsg)) {
                if (errormsg.equals("导入失败")) {
                    builder.append("失败异常信息:" + CommonUtil.getNewLine());
                    builder.append(exception.getMessage() + CommonUtil.getNewLine());
                    builder.append("失败堆栈信息:" + CommonUtil.getNewLine());
                    builder.append(exception.getStackTrace());
                } else {
                    builder.append("导入失败信息:" + errormsg + CommonUtil.getNewLine());
                }
            }
            LogUtil.writeLog("org/dept", "log", builder.toString());
        }
        return errormsg;
    }
}
